﻿#define  _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<utility>
#include<atomic>
#include<functional>
using namespace std;

template<class T>
class myshared_ptr {
private:
	T* _ptr;
	std::atomic<size_t>* _pcount;
	//定制删除器
	std::function<void(T*)> _del = [](T* ptr) {delete ptr; };

public:
	//无参构造函数
	myshared_ptr():_ptr(nullptr), _pcount(nullptr)
	{}
	//传参构造
	explicit  myshared_ptr(T* ptr):_ptr(ptr), _pcount(ptr ? new std::atomic<size_t>(1) : nullptr)
	{}
	//带删除器的构造
	template<class D>
	myshared_ptr(T* ptr, D del) : _ptr(ptr), _pcount(ptr ? new std::atomic<size_t>(1) : nullptr),_del(del)
	{}

	//拷贝构造
     myshared_ptr(const myshared_ptr& sptr):_ptr(sptr._ptr), _pcount(sptr._pcount), _del(sptr._del)
	{
		if (_pcount) {
			++(*_pcount);
		}
	}
	//移动构造
	 myshared_ptr(myshared_ptr&& sptr):
		 _ptr(std::exchange(sptr._ptr, nullptr)),
		_pcount(std::exchange(sptr._ptr, nullptr)),
		 _del(std::move(sptr._del))
	 {

	 }

	 //移动赋值
	 myshared_ptr& operator=(myshared_ptr&& sptr)
	 {
		 if (_ptr != sptr._ptr)
		 {
			 release();
			 _ptr = std::exchange(sptr._ptr, nullptr);
			 _pcount = std::exchange(sptr._ptr, nullptr);
			 _del = std::move(sptr._del);
			 ++(*_pcount);
		 }
		 return *this;
	 }
	void release()
	{
		if (--(*_pcount) == 0)
		{
			_del(_ptr);
			delete _pcount;
		}
		_ptr = nullptr;
		_pcount = nullptr;
		_del = [](T* ptr) {delete ptr; };
	}
	
	//赋值构造
	myshared_ptr& operator=(const myshared_ptr& sptr)
	{
		if (_ptr != sptr._ptr) {
			this->release();
			_ptr = sptr._ptr;
			_pcount = sptr._pcount;
			_del = sptr._del;
			++(*_pcount);
		}
		return *this;
	}
	//*
	T& operator*()
	{
		return *_ptr;
	}

	T* operator->()
	{
		return _ptr;
	}
	size_t use_count()
	{
		return *_pcount;
	}
	T& get()
	{
		return _ptr;
	}

	operator bool()
	{
		return _ptr != nullptr;
	}

	~myshared_ptr()
	{
		release();
	}
};

class A
{
public:
	A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{
	}
	A()
	{
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a1 = 1;
	int _a2 = 1;
};

template<class T>
struct FreeFunc {
	void operator()(T* ptr)
	{
		cout << "free:" << ptr << endl;
		free(ptr);
	}
};

int main()
{
	myshared_ptr<int> sp1(new int);
	//myshared_ptr<int> sp2(sp1);
	myshared_ptr<int> sp2 = sp1;
	

	//std::shared_ptr<A[]> sp4(new A[10]);

										//lambda
	//myshared_ptr<A> sp1(new A[10], [](A* ptr) {delete[] ptr; });
	//º
	//myshared_ptr<int> sp2((int*)malloc(4), FreeFunc<int>());
	//lambda
	myshared_ptr<FILE> sp3(fopen("test.txt", "w"), [](FILE* ptr) { fclose(ptr); });
	//myshared_ptr<A> sp4(new A);


	cout << sp1.use_count() << endl;
	return 0;
}